import psutil
import time
import json
from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

# 存储CPU历史数据
CPU_HISTORY = []
MAX_HISTORY = 30  # 保留最近30个数据点

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/system_info')
def get_system_info():
    try:
        # CPU信息
        cpu_percent = psutil.cpu_percent(interval=0.1)
        cpu_count = psutil.cpu_count(logical=False)
        cpu_count_logical = psutil.cpu_count(logical=True)
        
        # 记录CPU历史数据
        timestamp = time.time()
        CPU_HISTORY.append((timestamp, cpu_percent))
        if len(CPU_HISTORY) > MAX_HISTORY:
            CPU_HISTORY.pop(0)
        
        # 内存信息
        memory = psutil.virtual_memory()
        
        # 磁盘信息
        disk = psutil.disk_usage('/')
        
        # 网络信息
        network = psutil.net_io_counters()
        
        return jsonify({
            'timestamp': timestamp,
            'cpu': {
                'percent': cpu_percent,
                'count': cpu_count,
                'count_logical': cpu_count_logical,
                'history': CPU_HISTORY
            },
            'memory': {
                'total': memory.total,
                'used': memory.used,
                'percent': memory.percent
            },
            'disk': {
                'total': disk.total,
                'used': disk.used,
                'percent': disk.percent
            },
            'network': {
                'bytes_sent': network.bytes_sent,
                'bytes_recv': network.bytes_recv
            }
        })
    except Exception as e:
        return jsonify({
            'error': str(e),
            'message': '获取系统信息失败'
        }), 500

@app.route('/api/processes')
def get_processes():
    try:
        sort_by = request.args.get('sort_by', 'cpu_percent')
        order = request.args.get('order', 'desc')
        search = request.args.get('search', '').lower()
        
        processes = []
        for proc in psutil.process_iter(['pid', 'name', 'username', 'status', 'cpu_percent', 'memory_percent', 'memory_info', 'num_threads', 'create_time']):
            try:
                process_info = proc.info
                process_info['create_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(process_info['create_time']))
                process_info['cmdline'] = proc.cmdline()
                
                # 确保内存信息结构完整
                memory_info = process_info.get('memory_info', {})
                process_info['memory_info'] = {
                    'rss': getattr(memory_info, 'rss', 0),
                    'vms': getattr(memory_info, 'vms', 0)
                }
                
                # 确保CPU和内存百分比为数值类型
                process_info['cpu_percent'] = float(process_info.get('cpu_percent', 0))
                process_info['memory_percent'] = float(process_info.get('memory_percent', 0))
                
                # 过滤搜索结果
                if search and (
                    search not in str(process_info['pid']).lower() and
                    search not in process_info['name'].lower() and
                    (process_info['username'] and search not in process_info['username'].lower())
                ):
                    continue
                
                processes.append(process_info)
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        
        # 排序
        reverse = (order == 'desc')
        processes.sort(key=lambda p: p.get(sort_by, 0), reverse=reverse)
        
        return jsonify(processes)
    except Exception as e:
        return jsonify({
            'error': str(e),
            'message': '获取进程列表失败'
        }), 500

@app.route('/api/processes/<int:pid>/terminate', methods=['POST'])
def terminate_process(pid):
    try:
        process = psutil.Process(pid)
        
        # 先尝试温和终止
        if process.status() != psutil.STATUS_ZOMBIE:
            process.terminate()  # 发送SIGTERM信号
            time.sleep(0.1)  # 等待进程响应
            
            # 如果进程仍在运行，强制终止
            if process.is_running():
                process.kill()  # 发送SIGKILL信号
                return jsonify({
                    'message': f'已强制终止进程 {pid}'
                })
                
        return jsonify({
            'message': f'已成功终止进程 {pid}'
        })
        
    except psutil.NoSuchProcess:
        return jsonify({
            'message': f'进程 {pid} 不存在或已终止'
        }), 404
    except psutil.AccessDenied:
        return jsonify({
            'message': f'没有权限终止进程 {pid}，请以管理员身份运行'
        }), 403
    except Exception as e:
        return jsonify({
            'error': str(e),
            'message': f'终止进程 {pid} 失败'
        }), 500

if __name__ == '__main__':
    app.run(debug=True)